/*
 * Low-level routines to write the CIF file.
 *
 * Copyright (c) 2005-2007 Xaveer Leijtens
 *
 * This file is part of libMask.
 *
 * libMask is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * libMask is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with libMask.  If not, see <http://www.gnu.org/licenses/>.
 */
 
#include "cif.h"

extern void angle_vector(double, int*, int*);
extern double map_0_2pi(double);

/* Units are specified in meters, but written to cif file in nanometers. */

#define NM(x) ((x)*1e9)
//to avoid error due to the limitation of swig.20121108
/*double NM(double x)
{
  return ((x)*1e9);
}*/

/* Testing: in 10 nm grid */
/* #define NM(x) (round((x)*1e8)*10) */

/* Set the current layer */
void cif_layer(int n)
{
  layernr(n);
  clayer=n;
  if (drawlayer(n)) fprintf(MASK,"L L%03d;\n", n);
}

void cif_mskpolygon3(int l, double x1, double y1, double x2, double y2,
    double x3, double y3)
{
  if (drawlayer(l))
    fprintf(MASK,"P %.0f %.0f %.0f %.0f %.0f %.0f;\n",
      NM(x1),NM(y1),NM(x2),NM(y2),NM(x3),NM(y3));
}

void cif_mskpolygon4(int l, double x1, double y1, double x2, double y2,
    double x3, double y3, double x4, double y4)
{
  if (drawlayer(l))
    fprintf(MASK,"P %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f;\n",
      NM(x1),NM(y1),NM(x2),NM(y2),NM(x3),NM(y3),NM(x4),NM(y4));
}

void cif_mskpolygonN(int l, double *x, double *y, int n)
{
  int i;

  if (drawlayer(l)) {
    fprintf(MASK, "P");
    for (i=0; i<n; i++)
      fprintf(MASK, " %.0f %.0f", NM(x[i]), NM(y[i]));
    fprintf(MASK, ";\n");
  }
}

/* This routine uses three point on the arc to define it. For the CIF
 * routine, a CleWin specific extension is used, where the arc definition
 * is in a CIF comment. It is interpreted by clewin and written as polygon
 * (with course sampling!) to both CIF or GDS output files. In the CIF file
 * the CleArcWire is maintained and takes preference over the polygon that
 * follows. Bit of a cludge, and used primarily for debugging. It may also
 * be useful for Raith extensions (e.g. for fixed beam moving stage (FBMS)
 * structures.
 */
void cif_mskarc(int l, double w, double x1, double y1, double x2,
    double y2, double x3, double y3)
{
  double r, x0, y0;

  fprintf(stderr, "CIF Warning: CleWin specific arc used (and wrong at times).\n");
  if (drawlayer(l)) {
    /* Add nothing to width to get rounded ends of arcs
     * Add 0x10000000 = 268435456 to width to get straight ends of arc
     * Add 0x20000000 = 536870912 to width to get straight extended ends of arc
     *
     * Arguments are (width+code) (x_start,ystart) (x_center,y_center)
     * (x_end,y_end)
     */
    r = radius_3pts(x1, y1, x2, y2, x3, y3, &x0, &y0);
    if (r>0) {
      fprintf(MASK, "(CleArcWire %.0f %.0f %.0f %.0f %.0f %.0f %.0f)\n",
	NM(w)+0x10000000, NM(x3), NM(y3), NM(x0), NM(y0), NM(x1), NM(y1));
    } else {
      fprintf(MASK, "(CleArcWire %.0f %.0f %.0f %.0f %.0f %.0f %.0f)\n",
	NM(w)+0x10000000, NM(x1), NM(y1), NM(x0), NM(y0), NM(x3), NM(y3));
    }
  }
}

void cif_mskarc2 (int l, double w, double r, double a1, double a2, double x1,
    double y1)
{
  fprintf(stderr, "Error: mskarc2 (CIF) not implemented (but continuing...)\n");
}

void cif_mskcircle(int l, double w, double x1, double y1, double x2, double y2)
{
  if (drawlayer(l))
    fprintf(MASK, "R %.0f %.0f %.0f;\n",
      fabs(2*NM(x2-x1)), NM(x1), NM(y1));
}

void cif_mskpolystart(int l, double w)
{
  if (drawlayer(l))
    fprintf(MASK, "(CleWireStyle 1);\nW%.0f", NM(w));
}

void cif_mskpolypoint(int l, double x, double y)
{
  if (drawlayer(l))
    fprintf(MASK," %.0f %.0f",NM(x),NM(y));
}

void cif_mskpolyend(int l)
{
  if (drawlayer(l)) fprintf(MASK,";\n");
}

void cif_mskpolygonend(int l)
{
  cif_mskpolyend(l);
}

void cif_mskpolygonstart(int l)
{
  if (drawlayer(l)) fprintf(MASK, "P");
}

void cif_msk_main_header(const char *filename)
{
  struct Layer *layer;
  /* Grr: layers in clewin are BRG, not RGB!
   * They start with 0, followed with a hex number for the filling.
   *
   */
  const char *lc[17][2] = {
    {"0fdcdcdc 0fcccccc", "0fcccccc 0fcccccc"}, /* WHITE       */
    {"0f6060ff 0f0000ff", "0f0000ff 0f0000ff"}, /* RED         */
    {"0f90ffff 0f00e0ff", "0f00e0ff 0f00e0ff"}, /* YELLOW      */
    {"0f90ff90 0f00ff00", "0f00ff00 0f00ff00"}, /* GREEN       */
    {"0fffff60 0fffff00", "0fffff00 0fffff00"}, /* CYAN        */
    {"0fff6060 0fff0000", "0fff0000 0fff0000"}, /* BLUE        */
    {"0fff60ff 06ff00ff", "0fff00ff 0fff00ff"}, /* MAGENTA     */
    {"0f848484 0f444444", "0fc0c0c0 0f444444"}, /* BLACK       */
    {"0f608860 0f008800", "0f008800 0f008800"}, /* DK_GREEN    */
    {"0fffaa55 0fff8800", "0fff8800 0fff8800"}, /* AQUA        */
    {"0fa84040 0f880000", "0f880000 0f880000"}, /* DK_BLUE     */
    {"0fff50aa 0fff00aa", "0fff00aa 0fff00aa"}, /* PURPLE      */
    {"0fb000b0 0f880088", "0f880088 0f880088"}, /* MAUVE       */
    {"0f40a8ff 0f0088ff", "0f0088ff 0f0088ff"}, /* ORANGE      */
    {"0f3070a8 0f003388", "0f003388 0f003388"}, /* BROWN       */
    {"0f75a9cc 0f5599cc", "0f5599cc 0f5599cc"}, /* TAN         */
    {"0ffe62ff 0fffd2ff", "0fffd2ff 0fffd2ff"}, /* PINK        */
  };

  if (!strcmp(filename, "")) {
    MASK = stdout;
  } else if ((MASK = fopen(filename, "w")) == NULL) {
    fprintf(stderr, "Can't open '%s' for writing.\nError %d\n",
      filename, errno);
    exit(errno);
  }
  /* The first line is needed to get the proper layer names. */
  fprintf(MASK,"(CIF written by CleWin 3.2);\n");
  fprintf(MASK,"(Written by %s);\n", libMaskVersion());
  fprintf(MASK,"(1 unit = 0.001 micron);\n");
  fprintf(MASK,"(Opto-Electronic Devices Group);\n");
  fprintf(MASK,"(TU Eindhoven);\n");
  fprintf(MASK,"(Den Dolech 2);\n");
  fprintf(MASK,"(5600 MB Eindhoven);\n");
  fprintf(MASK,"(Layer names:);\n");

  clayer = layers->number; /* set default layer to first layer defined */
  for (layer=layers;layer->number>-1;layer++)
    if (layer->visible) {
//      sprintf(color, "%06x", lc[layer->color-1]);
      if (layer->number % 2) { /* Odd numbered layer: fine spot, hash pattern */
	fprintf(MASK,"L L%03d; (CleWin: %d %s/%s);\n",
	  layer->number, layer->number, layer->name, lc[layer->color-1][0]);
      } else { /* Odd numbered layer: coarse spot, filled */
	fprintf(MASK,"L L%03d; (CleWin: %d %s/%s);\n",
	  layer->number, layer->number, layer->name, lc[layer->color-1][1]);
      }
    }
}

void cif_msk_sublayout_header(const char *layout)
{
  static int SymbDef = 1;
  if (this_layout == MAIN_LAYOUT)
    fprintf(MASK, "(Top level:);\n");
  else if (SymbDef) {
    fprintf(MASK, "(Symbol definitions:);\n");
    SymbDef = 0;
  }
  /* Start sublayout definition with the first layer. */
  fprintf(MASK,"DS%d 1 10;\n9 %s;\nL L%03d;\n",
    this_layout+1, layout, layers->number);
}

void cif_msk_sublayout_trailer()
{
  fprintf(MASK,"DF;\n");
}

void cif_msk_trailer()
{
  cif_msk_sublayout_trailer();
  fprintf(MASK, "C %d;\nE\n", this_layout+1);
  fclose(MASK);
}

void cif_mskline(int l, double w, double xb, double yb, double xe, double ye)
{
  if (drawlayer(l))
    fprintf(MASK, "(CleWireStyle 1);\nW%.0f %.0f %.0f %.0f %.0f;\n",
      NM(w),NM(xb),NM(yb),NM(xe),NM(ye));
}

void cif_msklayout(const int layoutnr, const char *name, double a, double x,
    double y, int flip)
{
  int u, v;
  char rot[80];

  /*
  fprintf(stderr, "WARNING: sublayout rotation *VERY EXPERIMENTAL*\n");
  */
  angle_vector(a, &u, &v);
  sprintf(rot, " R%d %d", u, v);

  /* Flip: always about x-axis, which is MY... (?) */
  fprintf(MASK,"C %d%s%s T%.0f %.0f;\n",
      layoutnr+1, flip?" MY":"", rot, NM(x), NM(y));
}
